package com.flipdf2.serialize.ppml.element;

import java.util.ArrayList;
import java.util.List;

import org.jdom.Element;
import org.jdom.Namespace;

import com.flipdf2.serialize.ppml.AttributeType;
import com.flipdf2.serialize.ppml.PPMLException;
import com.flipdf2.serialize.ppml.element.imposition.PPMLImposition;
import com.flipdf2.serialize.ppml.element.imposition.PPMLPrintLayout;

public class PPML {
	public static final String NAME = "PPML";
	
	private List<PPMLConformance> conformanceList;
	private List<PPMLMetadata> metadataList;
	private PPMLTicket ticket;

	private PPMLSuppliedResources suppliedResources;
	private PPMLRequiredResources requiredResources;
	private List<PPMLImposition> impositionList;

	private PPMLPrintLayout printLayout;
	private PPMLPageDesign pageDesign;

	private List<PPMLPrivateInfo> privateInfoList;

	private List<PPMLTicketSet> ticketSetList;
	private List<PPMLTicketRef> ticketRefList;
	private List<PPMLReusableObject> reusableObjectList;
	private List<PPMLSegmentArray> segmentArrayList;
	private List<PPMLDocumentSet> documentSetList;
	private List<PPMLJob> jobList;

	private String version;
	private String datasetClass;
	private String creator;
	private String creationDate;
	private boolean resourcesIncluded;
	private boolean sheetLayoutIncluded;
	private String label;
	
	public Element toXML() {
		Namespace defaultNamespace = getNameSpace();
		
		Element root = null;
		if (defaultNamespace != null) {
			root = new Element(NAME, defaultNamespace);
		} else {
			root = new Element(NAME);	
		}
		root.addNamespaceDeclaration(Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
		root.setAttribute("schemaLocation", "urn://www.podi.org/ppml/ppml2 http://www.podi.org/ppml/ppml220.xsd", 
				Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
		
		if (conformanceList != null && conformanceList.size() > 0) {
			for (int i = 0, n = conformanceList.size(); i < n; i++) {
				root.addContent(conformanceList.get(i).toXML(defaultNamespace));
			}
		}
		
		if (metadataList != null && metadataList.size() > 0) {
			for (int i = 0, n = metadataList.size(); i < n; i++) {
				root.addContent(metadataList.get(i).toXML(defaultNamespace));
			}
		}
		
		if (ticket != null)
			root.addContent(ticket.toXML(defaultNamespace));
		
		if (suppliedResources != null)
			root.addContent(suppliedResources.toXML(defaultNamespace));
		
		if (requiredResources != null)
			root.addContent(requiredResources.toXML(defaultNamespace));
		
		if (impositionList != null && impositionList.size() > 0) {
			for (int i = 0, n = impositionList.size(); i < n; i++) {
				root.addContent(impositionList.get(i).toXML(defaultNamespace));
			}
		}
		
		if (printLayout != null)
			root.addContent(printLayout.toXML(defaultNamespace));

		if (pageDesign != null)
			root.addContent(pageDesign.toXML(defaultNamespace));
		
		if (privateInfoList != null && privateInfoList.size() > 0) {
			for (int i = 0, n = privateInfoList.size(); i < n; i++) {
				root.addContent(privateInfoList.get(i).toXML(defaultNamespace));
			}
		}
		
		if (ticketSetList != null && ticketSetList.size() > 0) {
			for (int i = 0, n = ticketSetList.size(); i < n; i++) {
				root.addContent(ticketSetList.get(i).toXML(defaultNamespace));
			}
		}

		if (ticketRefList != null && ticketRefList.size() > 0) {
			for (int i = 0, n = ticketRefList.size(); i < n; i++) {
				root.addContent(ticketRefList.get(i).toXML(defaultNamespace));
			}
		}
		
		if (reusableObjectList != null && reusableObjectList.size() > 0) {
			for (int i = 0, n = reusableObjectList.size(); i < n; i++) {
				root.addContent(reusableObjectList.get(i).toXML(defaultNamespace));
			}
		}

		if (segmentArrayList != null && segmentArrayList.size() > 0) {
			for (int i = 0, n = segmentArrayList.size(); i < n; i++) {
				root.addContent(segmentArrayList.get(i).toXML(defaultNamespace));
			}
		}

		if (documentSetList != null && documentSetList.size() > 0) {
			for (int i = 0, n = documentSetList.size(); i < n; i++) {
				root.addContent(documentSetList.get(i).toXML(defaultNamespace));
			}
		}
		
		if (jobList != null && jobList.size() > 0) {
			for (int i = 0, n = jobList.size(); i < n; i++) {
				root.addContent(jobList.get(i).toXML(defaultNamespace));
			}
		}
		
		if (version != null) 
			root.setAttribute("Version", version);
		if (datasetClass != null)
			root.setAttribute("Class", datasetClass);
		if (creator != null) 
			root.setAttribute("Creator", creator);
		if (creationDate != null) 
			root.setAttribute("CreationDate", creationDate.toString());
		if (resourcesIncluded) 
			root.setAttribute("ResourcesIncluded", AttributeType.PPMLBoolean.getString(resourcesIncluded));
		if (sheetLayoutIncluded) 
			root.setAttribute("SheetLayoutIncluded", AttributeType.PPMLBoolean.getString(sheetLayoutIncluded));
		if (label != null) 
			root.setAttribute("Label", label.toString());
		
		return root;
	}
	
	public void check() throws PPMLException {
		if (version == null) {
			throw PPMLException.getInstance(PPMLException.REQUIRED_ATTRIBUTE_LOST, "Version");
		}
		
		if (conformanceList != null && conformanceList.size() > 0) {
			for (int i = 0, n = conformanceList.size(); i < n; i++) {
				conformanceList.get(i).check();
			}
		}
		
		if (metadataList != null && metadataList.size() > 0) {
			for (int i = 0, n = metadataList.size(); i < n; i++) {
				metadataList.get(i).check();
			}
		}
		
		if (ticket != null)
			ticket.check();
		
		if (suppliedResources != null)
			suppliedResources.check();
		
		if (requiredResources != null)
			requiredResources.check();
		
		if (impositionList != null && impositionList.size() > 0) {
			for (int i = 0, n = impositionList.size(); i < n; i++) {
				impositionList.get(i).check();
			}
		}
		
		if (printLayout != null)
			printLayout.check();

		if (pageDesign != null)
			pageDesign.check();
		
		if (privateInfoList != null && privateInfoList.size() > 0) {
			for (int i = 0, n = privateInfoList.size(); i < n; i++) {
				privateInfoList.get(i).check();
			}
		}
		
		if (ticketSetList != null && ticketSetList.size() > 0) {
			for (int i = 0, n = ticketSetList.size(); i < n; i++) {
				ticketSetList.get(i).check();
			}
		}

		if (ticketRefList != null && ticketRefList.size() > 0) {
			for (int i = 0, n = ticketRefList.size(); i < n; i++) {
				ticketRefList.get(i).check();
			}
		}
		
		if (reusableObjectList != null && reusableObjectList.size() > 0) {
			for (int i = 0, n = reusableObjectList.size(); i < n; i++) {
				reusableObjectList.get(i).check();
			}
		}

		if (segmentArrayList != null && segmentArrayList.size() > 0) {
			for (int i = 0, n = segmentArrayList.size(); i < n; i++) {
				segmentArrayList.get(i).check();
			}
		}

		if (documentSetList != null && documentSetList.size() > 0) {
			for (int i = 0, n = documentSetList.size(); i < n; i++) {
				documentSetList.get(i).check();
			}
		}
		
		if (jobList != null && jobList.size() > 0) {
			for (int i = 0, n = jobList.size(); i < n; i++) {
				jobList.get(i).check();
			}
		}
	}
	
	private Namespace getNameSpace() {
		Namespace xmlns = null;
		if (version.equalsIgnoreCase("2.2")) {
			xmlns = Namespace.getNamespace("urn://www.podi.org/ppml/ppml2");
		}
		
		return xmlns;
	}
	
	public List<PPMLConformance> getConformanceList() {
		return conformanceList;
	}

	public void setConformanceList(List<PPMLConformance> conformanceList) {
		this.conformanceList = conformanceList;
	}
	
	public void addConformance(PPMLConformance conformance) {
		if (this.conformanceList == null)
			this.conformanceList = new ArrayList<PPMLConformance>();
		this.conformanceList.add(conformance);
	}

	public String getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(String creationDate) {
		this.creationDate = creationDate;
	}

	public String getCreator() {
		return creator;
	}

	public void setCreator(String creator) {
		this.creator = creator;
	}

	public String getDatasetClass() {
		return datasetClass;
	}

	public void setDatasetClass(String datasetClass) {
		this.datasetClass = datasetClass;
	}

	public List<PPMLDocumentSet> getDocumentSetList() {
		return documentSetList;
	}

	public void setDocumentSetList(List<PPMLDocumentSet> documentSetList) {
		this.documentSetList = documentSetList;
	}
	
	public void addDocumentSet(PPMLDocumentSet documentSet) {
		if (this.documentSetList == null)
			this.documentSetList = new ArrayList<PPMLDocumentSet>();
		this.documentSetList.add(documentSet);
	}

	public List<PPMLImposition> getImpositionList() {
		return impositionList;
	}

	public void setImpositionList(List<PPMLImposition> impositionList) {
		this.impositionList = impositionList;
	}
	
	public void addImposition(PPMLImposition imposition) {
		if (this.impositionList == null)
			this.impositionList = new ArrayList<PPMLImposition>();
		this.impositionList.add(imposition);
	}

	public List<PPMLJob> getJobList() {
		return jobList;
	}

	public void setJobList(List<PPMLJob> jobList) {
		this.jobList = jobList;
	}

	public void addJob(PPMLJob job) {
		if (this.jobList == null)
			this.jobList = new ArrayList<PPMLJob>();
		this.jobList.add(job);
	}
	
	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public List<PPMLMetadata> getMetadataList() {
		return metadataList;
	}

	public void setMetadataList(List<PPMLMetadata> metadataList) {
		this.metadataList = metadataList;
	}

	public void addMetadata(PPMLMetadata metadata) {
		if (this.metadataList == null)
			this.metadataList = new ArrayList<PPMLMetadata>();
		this.metadataList.add(metadata);
	}
	
	public PPMLPageDesign getPageDesign() {
		return pageDesign;
	}

	public void setPageDesign(PPMLPageDesign pageDesign) {
		this.pageDesign = pageDesign;
	}

	public PPMLPrintLayout getPrintLayout() {
		return printLayout;
	}

	public void setPrintLayout(PPMLPrintLayout printLayout) {
		this.printLayout = printLayout;
	}

	public List<PPMLPrivateInfo> getPrivateInfoList() {
		return privateInfoList;
	}

	public void setPrivateInfoList(List<PPMLPrivateInfo> privateInfoList) {
		this.privateInfoList = privateInfoList;
	}
	
	public void addPrivateInfo(PPMLPrivateInfo privateInfo) {
		if (this.privateInfoList == null)
			this.privateInfoList = new ArrayList<PPMLPrivateInfo>();
		this.privateInfoList.add(privateInfo);
	}

	public PPMLRequiredResources getRequiredResources() {
		return requiredResources;
	}

	public void setRequiredResources(PPMLRequiredResources requiredResources) {
		this.requiredResources = requiredResources;
	}

	public boolean isResourcesIncluded() {
		return resourcesIncluded;
	}

	public void setResourcesIncluded(boolean resourcesIncluded) {
		this.resourcesIncluded = resourcesIncluded;
	}

	public List<PPMLReusableObject> getReusableObjectList() {
		return reusableObjectList;
	}

	public void setReusableObjectList(List<PPMLReusableObject> reusableObjectList) {
		this.reusableObjectList = reusableObjectList;
	}
	
	public void addReusableObject(PPMLReusableObject reusableObject) {
		if (this.reusableObjectList == null)
			this.reusableObjectList = new ArrayList<PPMLReusableObject>();
		this.reusableObjectList.add(reusableObject);
	}

	public List<PPMLSegmentArray> getSegmentArrayList() {
		return segmentArrayList;
	}

	public void setSegmentArrayList(List<PPMLSegmentArray> segmentArrayList) {
		this.segmentArrayList = segmentArrayList;
	}
	
	public void addSegmentArray(PPMLSegmentArray segmentArray) {
		if (this.segmentArrayList == null)
			this.segmentArrayList = new ArrayList<PPMLSegmentArray>();
		this.segmentArrayList.add(segmentArray);
	}

	public boolean isSheetLayoutIncluded() {
		return sheetLayoutIncluded;
	}

	public void setSheetLayoutIncluded(boolean sheetLayoutIncluded) {
		this.sheetLayoutIncluded = sheetLayoutIncluded;
	}

	public PPMLSuppliedResources getSuppliedResources() {
		return suppliedResources;
	}

	public void setSuppliedResources(PPMLSuppliedResources suppliedResources) {
		this.suppliedResources = suppliedResources;
	}

	public PPMLTicket getTicket() {
		return ticket;
	}

	public void setTicket(PPMLTicket ticket) {
		this.ticket = ticket;
	}

	public List<PPMLTicketRef> getTicketRefList() {
		return ticketRefList;
	}

	public void setTicketRefList(List<PPMLTicketRef> ticketRefList) {
		this.ticketRefList = ticketRefList;
	}
	
	public void addTicketRef(PPMLTicketRef ticketRef) {
		if (this.ticketRefList == null)
			this.ticketRefList = new ArrayList<PPMLTicketRef>();
		this.ticketRefList.add(ticketRef);
	}

	public List<PPMLTicketSet> getTicketSetList() {
		return ticketSetList;
	}

	public void setTicketSetList(List<PPMLTicketSet> ticketSetList) {
		this.ticketSetList = ticketSetList;
	}
	
	public void addTicketSet(PPMLTicketSet ticketSet) {
		if (this.ticketSetList == null)
			this.ticketSetList = new ArrayList<PPMLTicketSet>();
		this.ticketSetList.add(ticketSet);
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}
}
